package model;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import utils.ImageUtils;
import utils.Parameters;
import view.MainFrame;

/**
 * Layer model
 * @author Hugo
 *
 */
public class Layer extends JPanel
{
    private BufferedImage m_image;
    private String        m_title;
    private int m_alpha;

    /**
     * Layer from a colour
     * @param width
     * @param height
     * @param colour
     * @param title
     * @param alpha
     */
    public Layer(int width, int height, Color colour, String title, int alpha)
    {
        super();
        m_alpha = alpha;
        m_title = title;
        this.setSize(width, height);

        m_image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = m_image.getGraphics();

        g.setColor(new Color(colour.getRed(), colour.getGreen(), colour
                .getBlue(), alpha));

        g.fillRect(0, 0, width, height);
        g.dispose();
    }

    /**
     * Empty layer (size of the document)
     */
    public Layer()
    {
        super();
        m_alpha =0;
        m_title = "sans titre " + MainFrame.getInstance().getCount();
        int width = MainFrame.getInstance().getDocumentWidth();
        int height = MainFrame.getInstance().getDocumentHeight();
        this.setSize(width, height);

        m_image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = m_image.getGraphics();

        g.setColor(new Color(0, 0, 0, 0));

        g.fillRect(0, 0, width, height);
        g.dispose();
    }

    /**
     * image layer
     * @param image
     */
    public Layer(ImageIcon image)
    {
        super();
        m_alpha = 255;
        m_title = image.getDescription();
        image.setImage(ImageUtils.resizeInferiorTo(
                image.getImage(), 
                MainFrame.getInstance().getDocumentWidth(), 
                MainFrame.getInstance().getDocumentHeight() )
                );
        int width = image.getImage().getWidth(null);
        int height = image.getImage().getHeight(null);
        this.setSize(width, height);

        m_image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = m_image.getGraphics();

        g.drawImage(image.getImage(), 0, 0, null);

        g.dispose();
    }

    /**
     * Text Layer
     * @param font
     * @param foreground
     * @param text
     */
    public Layer(Font font, Color foreground, String text)
    {
        super();
        m_alpha = 0;
        m_title = text;
        int width = MainFrame.getInstance().getDocumentWidth();
        int height = MainFrame.getInstance().getDocumentHeight();
        this.setSize(width, height);

        m_image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = m_image.getGraphics();
        g.setColor(foreground);
        g.setFont(font);
        // add in the middle of the height
        g.drawString(text, 10, height/2);
        g.dispose();
    }

    /**
     * create a layer from another layer, but crop it from the topLeftPoint to the bottomRightPoint
     * @param image
     * @param topLeftPoint
     * @param bottomRightPoint
     */
    public Layer(Layer layerSrc, Point topLeftPoint, Point bottomRightPoint)
    {
        super();
        m_alpha = layerSrc.getAlpha();
        m_title = layerSrc.getTitle()+"_cut";
        
        int width = (int)(bottomRightPoint.getX() - topLeftPoint.getX());
        int height = (int)(bottomRightPoint.getY() - topLeftPoint.getY());
        this.setSize(width, height);
        
        m_image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        
        for (int i = (int)(topLeftPoint.getX()) ; i < (int)(bottomRightPoint.getX()) ; ++i){
            for (int j = (int)(topLeftPoint.getY()) ; j < (int)(bottomRightPoint.getY()) ; ++j){
                m_image.setRGB(
                        i - (int)(topLeftPoint.getX()),
                        j - (int)(topLeftPoint.getY()),
                        layerSrc.getImage().getRGB(i, j));
                                
                layerSrc.getImage().setRGB(i, j, Color.TRANSLUCENT);
            }
        }   
    }
    
    @Override
    protected void paintComponent(Graphics g)
    {
        if (m_image != null)
        {
            g.drawImage(m_image, 0, 0, null);
        }
    }
    
    public void resizeImage(int width, int height)
    {
        m_image = ImageUtils.resizeTo(m_image, width, height );
    }

    public void drawPoint(Color color, int prevX, int prevY, int x, int y)
    {
        Graphics g = m_image.getGraphics();
        g.setColor(color);
        g.drawLine(prevX, prevY, x, y);
        g.dispose();
    }

    public void drawBrush(Color color, int size, int prevX, int prevY, int x, int y)
    {
        Graphics g = m_image.getGraphics();
        g.setColor(color);
        g.drawLine(prevX, prevY, x, y);
        for (int i = 0; i < size ; ++i){
            g.drawLine(prevX, prevY+i, x, y+i);
        }
        g.dispose();
    }
    
    public void erase(int size, int x, int y)
    {
        Graphics g = m_image.getGraphics();
        
        for (int i = -(size/2) ; i <= (size/2) ; ++i){
            for (int j = -(size/2) ;j <= (size/2) ; ++j){
                int newX;
                int newY;
                newX = ( x+i < 0) ? 0 : x+i;
                newX = ( newX >= this.getWidth() ) ? this.getWidth()-1 : newX;
                newY = ( y+j < 0) ? 0 : y+j;
                newY = ( newY >= this.getHeight() ) ? this.getHeight()-1 : newY;
                
                m_image.setRGB( newX, newY, Color.TRANSLUCENT);
            }
        }        
        
        g.dispose();
    }

    public void drawSpray(Color color, int size, int x, int y)
    {
        int pointSize = Parameters.SPRAY_POINT_SIZE;
        Graphics g = m_image.getGraphics();
        g.setColor(color);
        
        Random rand = new Random();
        for (int i = 0; i < Parameters.SPRAY_DENSITY+size ; ++i){
            int aleaX = rand.nextInt(size*2);
            int aleaY = rand.nextInt(size*2);
            double positive = Math.random();
            if (positive < 0.25){
                g.fillRect(x+aleaX, y+aleaY, pointSize, pointSize);
            }
            else if (positive < 0.5){
                g.fillRect(x+aleaX, y-aleaY, pointSize, pointSize);
            }
            else if (positive < 0.75){
                g.fillRect(x-aleaX, y+aleaY, pointSize, pointSize);
            }
            else{
                g.fillRect(x-aleaX, y-aleaY, pointSize, pointSize);
            }
        }        
        g.dispose();
    }
    
    public void rotate(int angle) {
        int imageWidth = this.getWidth();
        int imageHeight = this.getHeight();
        int distanceX = (imageWidth / 2);
        int distanceY = (imageHeight / 2);
        
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.translate(distanceX, distanceY);
        affineTransform.rotate(Math.toRadians(angle));
        affineTransform.translate(-distanceX, -distanceY);

        Graphics g = m_image.getGraphics();
        BufferedImage finaleImage = ImageUtils.deepCopy(m_image);


        for (int x = 0; x < m_image.getWidth(); ++x)
            for (int y = 0; y < m_image.getHeight(); ++y)
                m_image.setRGB(x, y, Color.TRANSLUCENT);
        ((Graphics2D) g).drawImage(finaleImage, affineTransform, this);

    }

    //------Getters & Setters-----//
    
    public int getAlpha() {
		return m_alpha;
	}

	public void setAlpha(int alpha) {
		this.m_alpha = alpha;
	}

	public BufferedImage getImage()
    {
        return m_image;
    }

    public void setImage(BufferedImage image)
    {
        this.m_image = image;
    }

    public String getTitle()
    {
        return m_title;
    }

    public void setTitle(String title)
    {
        this.m_title = title;
    }

    

    
}
